package com.uam.core.lk.utils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class DateTimeUtils {

    public enum DateTimeFormat {
        LEGACY_LOCAL_DATE_TIME(
            "LegacyLocal",
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
        LEGACY_OFFSET_DATE_TIME(
            "LegacyOffset",
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ")),
        ISO_LOCAL_DATE_TIME(
            "IsoLocal",
            DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")),
        ISO_OFFSET_DATE_TIME(
            "IsoOffset",
            DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));

        private final String name;
        private final DateTimeFormatter dateTimeFormatter;

        private DateTimeFormat(String name, DateTimeFormatter dateTimeFormatter) {
            this.name = name;
            this.dateTimeFormatter = dateTimeFormatter;
        }

        public String getName() {
            return name;
        }

        public DateTimeFormatter getDateTimeFormatter() {
            return dateTimeFormatter;
        }
    }

    public static String date2String(Date date, ZoneId zoneId, DateTimeFormat dateTimeFormat) {
        // return LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("Asia/Shanghai"))
        // .format(LEGACY_LOCAL_DATE_TIME_FORMATTER);
        switch (dateTimeFormat) {
            case LEGACY_LOCAL_DATE_TIME:
            case ISO_LOCAL_DATE_TIME:
                return LocalDateTime.ofInstant(date.toInstant(), zoneId).format(dateTimeFormat.getDateTimeFormatter());
            case LEGACY_OFFSET_DATE_TIME:
            case ISO_OFFSET_DATE_TIME:
                return ZonedDateTime.ofInstant(date.toInstant(), zoneId).format(dateTimeFormat.getDateTimeFormatter());
            default:
                return "";
        }

    }

    public static Instant date2Instant(Date date) {
        return date.toInstant();
    }

    public static String instant2String(Instant instant, ZoneId zoneId, DateTimeFormat dateTimeFormat) {
        switch (dateTimeFormat) {
            case LEGACY_LOCAL_DATE_TIME:
            case ISO_LOCAL_DATE_TIME:
                return LocalDateTime.ofInstant(instant, zoneId).format(dateTimeFormat.getDateTimeFormatter());
            case LEGACY_OFFSET_DATE_TIME:
            case ISO_OFFSET_DATE_TIME:
                return ZonedDateTime.ofInstant(instant, zoneId).format(dateTimeFormat.getDateTimeFormatter());
            default:
                return "";
        }
    }

    public static Date instant2Date(Instant instant) {
        return Date.from(instant);
    }

    public static Date string2Date(String dateString, ZoneId zoneId, DateTimeFormat dateTimeFormat) {
        switch (dateTimeFormat) {
            case LEGACY_LOCAL_DATE_TIME:
            case ISO_LOCAL_DATE_TIME:
                return Date
                    .from(LocalDateTime.parse(dateString, dateTimeFormat.getDateTimeFormatter()).atZone(zoneId)
                        .toInstant());
            case LEGACY_OFFSET_DATE_TIME:
            case ISO_OFFSET_DATE_TIME:
                return Date
                    .from(ZonedDateTime.parse(dateString, dateTimeFormat.getDateTimeFormatter()).toInstant());
            default:
                return null;
        }

    }

    public static Instant string2Instant(String dateString, ZoneId zoneId, DateTimeFormat dateTimeFormat) {
        switch (dateTimeFormat) {
            case LEGACY_LOCAL_DATE_TIME:
            case ISO_LOCAL_DATE_TIME:
                return LocalDateTime.parse(dateString, dateTimeFormat.getDateTimeFormatter()).atZone(zoneId)
                    .toInstant();
            case LEGACY_OFFSET_DATE_TIME:
            case ISO_OFFSET_DATE_TIME:
                return ZonedDateTime.parse(dateString, dateTimeFormat.getDateTimeFormatter()).toInstant();
            default:
                return null;
        }
    }

    public static void main(String[] args) {
        String s = date2String(new Date(), ZoneId.of("Asia/Shanghai"), DateTimeFormat.LEGACY_LOCAL_DATE_TIME);
        System.out.println("LEGACY_LOCAL_DATE_TIME: " + s);
        s = date2String(new Date(), ZoneId.of("Asia/Shanghai"), DateTimeFormat.LEGACY_OFFSET_DATE_TIME);
        System.out.println("LEGACY_OFFSET_DATE_TIME: " + s);
        s = date2String(new Date(), ZoneId.of("Asia/Shanghai"), DateTimeFormat.ISO_LOCAL_DATE_TIME);
        System.out.println("ISO_LOCAL_DATE_TIME: " + s);
        s = date2String(new Date(), ZoneId.of("Asia/Shanghai"), DateTimeFormat.ISO_OFFSET_DATE_TIME);
        System.out.println("ISO_OFFSET_DATE_TIME: " + s);

        Date date = string2Date("2018-10-03T22:15:14.871+0800", ZoneId.systemDefault(),
            DateTimeFormat.ISO_OFFSET_DATE_TIME);
        System.out.println("ISO_OFFSET_DATE_TIME: " + date);
        date = string2Date("2018-10-03 22:15:14", ZoneId.systemDefault(), DateTimeFormat.LEGACY_LOCAL_DATE_TIME);
        System.out.println("ISO_OFFSET_DATE_TIME: " + date);
    }

    private DateTimeUtils() {

    }
}
